/********************************************************************************
 * @file    app_wifi.c
 * @brief   wifi通讯应用逻辑处理
 * 
 * @author  nzttj
 * @date    2025-02-14
 * @version 1.0
 * 
 * Copyright (C) 2025 nzttj
 * 
 * 本软件使用 GNU 通用公共许可证 (GPL) 第 3 版授权。
 * 
 * 您可以自由使用、修改、分发本软件，但必须遵守以下条件：
 * 1. 源代码必须开放，且您修改后的代码也必须以 GPL 许可证发布。
 * 2. 发布或分发本软件时，必须附带本许可证，并提供源代码或获取源代码的方式。
 * 
 * 本软件按“原样”提供，不附带任何担保，使用风险由用户自行承担。
 * 
 ********************************************************************************/

#include "app_wifi.h"
#include "hal_wifi.h"
#include "app_mqtt.h"
#include "app_provisioning.h"
#include "app_ota.h"
#include "app_tcp_server.h"
#include "app_mdns.h"
#include "hal_sntp.h"
#include "app_udp.h"

#include <stdio.h>
#include <string.h>

#include "esp_log.h"

#define APP_WIFI_AP_SSID "smart-socket-"
#define APP_WIFI_AP_PWD  "12345678"

static const char *TAG = "app_wifi";
static app_wifi_info_t s_wifi_info = {0};

/**
 * @brief 处理 Wi-Fi 事件
 * @param event_id 事件 ID
 * @param event_data 事件数据
 */
static void _wifi_event_callback(hal_wifi_event_t event_id, void *event_data)
{
    switch (event_id)
    {
    case HAL_WIFI_EVENT_STA_START:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_STA_START");
        s_wifi_info.sta_started = true;
        hal_wifi_connect();
        break;
    case HAL_WIFI_EVENT_STA_STOP:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_STA_STOP");
        s_wifi_info.sta_started = false;
        break;
    case HAL_WIFI_EVENT_STA_DISCONNECTED:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_STA_DISCONNECTED");
        if (s_wifi_info.sta_started)
        {
            hal_wifi_connect();
        }
        break;
    case HAL_WIFI_EVENT_AP_START:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_AP_START");
        app_tcp_server_init();
        app_provisioning_init();
        break;
    case HAL_WIFI_EVENT_AP_STOP:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_AP_STOP");
        break;
    case HAL_WIFI_EVENT_AP_STACONNECTED:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_AP_STACONNECTED");
        break;
    case HAL_WIFI_EVENT_AP_STADISCONNECTED:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_AP_STADISCONNECTED");
        break;
    case HAL_WIFI_EVENT_STA_GOT_IP:
        ESP_LOGI(TAG, "HAL_WIFI_EVENT_STA_GOT_IP");
        app_tcp_server_init();
        app_udp_init();
        app_mdns_deinit();
        app_mdns_init();
        if (strlen(app_ota_get_cfg()->url) > 0)
        {
            app_ota_init(app_ota_get_cfg());
        }
        app_mqtt_init();
        // hal_sntp_init();
        break;
    default:
        ESP_LOGI(TAG, "unknown event: %d", event_id);
        break;
    }
}

/**
 * @brief 初始化 Wi-Fi STA 模式
 * @details 使用已保存的连接信息配置 Wi-Fi STA 模式
 * @return 成功返回 0，失败返回负值
 */
static int _wifi_init_sta(void)
{
    hal_wifi_sta_cfg_t sta_config = {
        .ssid = s_wifi_info.conn_info.ssid,
        .password = s_wifi_info.conn_info.pwd,
    };

    return hal_wifi_init_sta(&sta_config);
}

/**
 * @brief 初始化 Wi-Fi AP 模式
 * @details 使用默认配置初始化 Wi-Fi AP 模式
 * @return 成功返回 0，失败返回负值
 */
static int _wifi_init_ap(void)
{
    uint8_t mac[6] = {0};
    char ssid[32] = {0};

    hal_wifi_ap_cfg_t ap_config = {
        .ssid = ssid,
        .password = APP_WIFI_AP_PWD,
        .max_connections = 3,
        .channel = 1,
    };

    hal_wifi_get_mac(HAL_WIFI_IF_AP, mac);
    snprintf(ssid, sizeof(ssid), "%s%02x%02x%02x", APP_WIFI_AP_SSID, mac[3], mac[4], mac[5]);

    return hal_wifi_init_ap(&ap_config);
}

int app_wifi_init(void)
{
    hal_wifi_init();
    hal_wifi_register_event_callback(_wifi_event_callback);

    if (s_wifi_info.mode == HAL_WIFI_MODE_STA)
    {
        return _wifi_init_sta();
    }
    else if (s_wifi_info.mode == HAL_WIFI_MODE_AP)
    {
        return _wifi_init_ap();
    }
    else
    {
        hal_wifi_deinit();
        return -1;
    }
}

int app_wifi_connect_to_new_ap(const char *ssid, const char *pwd)
{
    hal_wifi_stop();
    hal_wifi_sta_cfg_t sta_config = {
        .ssid = ssid,
        .password = pwd,
    };
    return hal_wifi_init_sta(&sta_config);
}

app_wifi_info_t *app_wifi_get_info(void)
{
    return &s_wifi_info;
}
